﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TcpAsyncClient
{
    public partial class Form1 : Form
    {

        private TcpClient tcpClient;
        private NetworkStream networkStream;
        private BinaryReader binaryReader;
        private BinaryWriter binaryWriter;
        // 声明委托
        private delegate void ShowMessage(string str);
        private ShowMessage showMessage;
        private delegate void ShowStatus(string str);
        private ShowStatus showStatus;
        private delegate void ShowProgress(int progress);
        private ShowProgress showProgress;
        private delegate void ResetText();
        private ResetText resetText;
        // 异步调用
        private delegate void ReceiveMessageDelegate(out string receiveMessage);
        private ReceiveMessageDelegate receiveMessageDelegate;
        private delegate void SendMessageDelegate(string sendMessage);
        private SendMessageDelegate sendMessageDelegate;

        public Form1()
        {
            InitializeComponent();
            showMessage = new ShowMessage(ShwMsgForView);
            showStatus = new ShowStatus(ShwStatusInfo);
            showProgress = new ShowProgress(ShwProgressProc);
            resetText = new ResetText(ResetMsgText);
            receiveMessageDelegate = new ReceiveMessageDelegate(AsyncRcvMsg);
            sendMessageDelegate = new SendMessageDelegate(AsyncSendMsg);
        }

        private void ShwMsgForView(string str)
        {
            str = System.DateTime.Now.ToString() + Environment.NewLine + "str" + Environment.NewLine;
            int txtGetTextLength = this.richTextBox1.Text.Length;
            this.richTextBox1.AppendText(str);
            this.richTextBox1.Select(txtGetTextLength, str.Length - Environment.NewLine.Length * 2 - str.Length);
            this.richTextBox1.SelectionColor = Color.Red;
            this.richTextBox1.ScrollToCaret();
        }

        /// <summary>
        /// 显示状态
        /// </summary>
        /// <param name="str"></param>
        private void ShwStatusInfo(string str)
        {
            toolStripStatusLabel1.Text = str;
        }

        /// <summary>
        /// 显示进度
        /// </summary>
        /// <param name="proc"></param>
        private void ShwProgressProc(int proc)
        {
            toolStripProgressBar1.Value = proc;
        }

        /// <summary>
        /// 重置文本
        /// </summary>
        private void ResetMsgText()
        {
            richTextBox1.Text = " ";
            richTextBox1.Focus();
        }

        /// <summary>
        /// 异步接收消息
        /// </summary>
        private void AsyncRcvMsg(out string? str)
        {
            str = null;
            try
            {
                str = binaryReader.ReadString();
            }
            catch (Exception ex)
            {
                if (binaryReader != null)
                {
                    binaryReader.Close();
                }
                if (binaryWriter != null)
                {
                    binaryWriter.Close();
                }
                if (tcpClient != null)
                {
                    tcpClient.Close();
                }
                statusStrip1.Invoke(showStatus, "连接断开!");
                statusStrip1.Invoke(showProgress, 0);
            }
        }

        /// <summary>
        /// 异步发送消息
        /// </summary>
        /// <param name="str"></param>
        private void AsyncSendMsg(string str)
        {
            try
            {
                binaryWriter.Write(str);
                DateTime dateTime = DateTime.Now;
                while (dateTime.AddSeconds(5) > DateTime.Now) { }
                binaryWriter.Flush();
            }
            catch (Exception ex)
            {
                if (binaryReader != null)
                {
                    binaryReader.Close();
                }

                if (binaryWriter != null)
                {
                    binaryWriter.Close();
                }

                if (tcpClient != null)
                {
                    tcpClient.Close();
                }

                statusStrip1.Invoke(showStatus, "连接断开!");
                statusStrip1.Invoke(showProgress, 0);
            }
        }

        /// <summary>
        /// 连接服务端
        /// </summary>
        private void ConnectToServer()
        {
            AsyncCallback asyncCallback = new AsyncCallback(RequestCallBack);
            statusStrip1.Invoke(showStatus, "正在连接");
            statusStrip1.Invoke(showProgress, 1);
            tcpClient = new TcpClient(AddressFamily.InterNetwork);
            IAsyncResult asyncResult = tcpClient.BeginConnect(IPAddress.Parse(textBox1.Text), 5656, asyncCallback, tcpClient);
            while (asyncResult.IsCompleted == true)
            {
                Thread.Sleep(30);
            }
        }

        /// <summary>
        /// 发起连接请求
        /// </summary>
        /// <param name="state"></param>
        private void RequestCallBack(IAsyncResult asyncResult)
        {
            try
            {
                tcpClient = (TcpClient)asyncResult.AsyncState;
                tcpClient.EndConnect(asyncResult);
                statusStrip1.Invoke(showProgress, 100);
                DateTime dateTime = DateTime.Now;
                while (dateTime.AddSeconds(1) > DateTime.Now) { }
                if (tcpClient != null)
                {
                    statusStrip1.Invoke(showStatus, "连接成功!");
                    networkStream = tcpClient.GetStream();
                    binaryReader = new BinaryReader(networkStream);
                    binaryWriter = new BinaryWriter(networkStream);
                }
            }
            catch (Exception ex)
            {
                statusStrip1.Invoke(showStatus, "连接失败");
                DateTime dateTime = DateTime.Now;
                while (dateTime.AddSeconds(1) > DateTime.Now) { }
                statusStrip1.Invoke(showProgress, 0);
                statusStrip1.Invoke(showStatus, "准备就绪");
            }
        }

        private void ReceiveMessage()
        {
            statusStrip1.Invoke(showStatus, "接收中...");
            string receiveString = null;
            for (int i = 0; i < 5; i++)
            {
                try
                {
                    IAsyncResult asyncResult = receiveMessageDelegate.BeginInvoke(out receiveString, null, null);
                    int j = 1;
                    while (asyncResult.IsCompleted == false)
                    {
                        statusStrip1.Invoke(showProgress, j);
                        j++;
                        if (j == 5)
                        {
                            j = 0;
                        }
                        Thread.Sleep(1000);
                    }
                    receiveMessageDelegate.EndInvoke(out receiveString, asyncResult);
                    statusStrip1.Invoke(showProgress, 5);

                    if (receiveString != null)
                    {
                        richTextBox2.Invoke(showMessage, receiveString);
                    }
                }
                catch
                {
                    DateTime now = DateTime.Now;
                    while (now.AddSeconds(2) > DateTime.Now) { }
                    break;
                }
            }
            statusStrip1.Invoke(showStatus, "接受了" + 5 + "条消息");
        }

        private void SendMessage(object state)
        {
            statusStrip1.Invoke(showStatus, "正在发送...");
            for (int i = 0; i < 5; i++)
            {
                try
                {
                    IAsyncResult asyncResult = sendMessageDelegate.BeginInvoke(state.ToString(), null, null);
                    while (asyncResult.IsCompleted == false)
                    {
                        Thread.Sleep(1000);
                    }
                    sendMessageDelegate.EndInvoke(asyncResult);
                    statusStrip1.Invoke(showProgress, i + 1);
                }
                catch (Exception e)
                {
                    DateTime dateTime = DateTime.Now;
                    while (dateTime.AddSeconds(2) > DateTime.Now) { }
                    break;
                }
            }
            statusStrip1.Invoke(showStatus, "完毕");
            DateTime dateTime1 = DateTime.Now;
            while (dateTime1.AddSeconds(1) > DateTime.Now) { }
            statusStrip1.Invoke(showProgress, 0);
            richTextBox1.Invoke(resetText, null);
        }

        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            toolStripProgressBar1.Maximum = 100;
            toolStripProgressBar1.Value = 0;
            Thread thread = new Thread(ConnectToServer);
            thread.Start();
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            toolStripProgressBar1.Maximum = 5;
            toolStripProgressBar1.Value = 0;
            Thread thread = new Thread(new ParameterizedThreadStart(SendMessage));
            thread.Start();
        }

        /// <summary>
        /// 接收消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            toolStripProgressBar1.Maximum = 5;
            toolStripProgressBar1.Value = 0;
            Thread thread = new Thread(ReceiveMessage);
            thread.Start();
        }

        /// <summary>
        /// 窗口关闭关闭所有资源
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="formClosedEventArgs"></param>
        private void Form1_FormClosing(object sender, FormClosedEventArgs formClosedEventArgs)
        {
            if (binaryReader != null)
            {
                binaryReader.Close();
            }
            if (binaryWriter != null)
            {
                binaryWriter.Close();
            }
            if (tcpClient != null)
            {
                tcpClient.Close();
            }
        }
    }
}
